using System.Collections.Generic;
using System.Data;
using System.Data.Objects.DataClasses;
using System.Linq;

namespace EntityFramework.ServiceLayer
{
    public interface IGenericRepository
    {
         /* NOTE:
          * Do NOT change the order of method declarations here:
          * it will cause an exception when trying to debuging entityframeworktests.
          * 
          * See more info here:
          * http://ayende.com/Blog/archive/2008/08/13/How-.Net-3.5-SP1-broke-Rhino-Mocks.aspx
          */

        //NOTE: This would have been such a nice solution :(
        //void UpdateReference<TEntity, TId>(EntityReference<TEntity> reference, TId id)
        //    where TEntity : EntityObject, IEntity<TId>;

        TEntity Get<TEntity>(object id)
            where TEntity : EntityObject, IEntity;

        IEnumerable<TEntity> GetAll<TEntity>()
            where TEntity : IEntity;
    }

    public class GenericRepository : IGenericRepository
    {
        private readonly IActiveObjectContextManager activeObjectContextManager;

        public GenericRepository(IActiveObjectContextManager activeObjectContextManager)
        {
            this.activeObjectContextManager = activeObjectContextManager;
        }

        protected IObjectContext ObjectContext
        {
            get { return activeObjectContextManager.GetActiveObjectContext(); }
        }

        //NOTE: This would have been such a nice solution :(
        //public void UpdateReference<TEntity, TId>(EntityReference<TEntity> reference, TId id)
        //    where TEntity : EntityObject, IEntity<TId>
        //{
        //    reference.EntityKey = ObjectContext.CreateEntityKey<TEntity, TId>(id);
        //}

        public TEntity Get<TEntity>(object id) 
            where TEntity : EntityObject, IEntity
        {
            if (id == null)
            {
                return null;
            }

            var entityKey = ObjectContext.CreateEntityKey<TEntity, object>(id);

            try
            {
                return (TEntity)ObjectContext.GetObjectByKey(entityKey);
            }
            catch (ObjectNotFoundException)
            {
                return null;
            }
        }

        public IEnumerable<TEntity> GetAll<TEntity>() where TEntity : IEntity
        {
            return ObjectContext.CreateQuery<TEntity>().ToList();
        }
    }
}